#include "cli.h"
#include "menu_cli.h"
//#include "cli_func.h"
#include <string.h>

static const cli_str* acpi;
static str_t tkn;
static char msg_dest[MAX_TAM_SIZE_STRING];

extern cli_str const api_cli[];				/* - tabela de parametros */
static const cli_str* menu_cli = api_cli;

/*
 * Função tratadora da entrada de comando, monta a estrutura.
 * Returna 0 se ok, -1 se errro.
 * 
 * */
int mount_token(char *data)
{
	char* buff="\0";
	//char buff[MAX_COMMAND_SIZE];
	U08_t i,j;

	if((j = strlen(data))==0){
		DEBUG_ERROR(INVALID_DATA);
		return -1;
	}
	else {
		for(i=0;i<j;i++){	//Passa todo o texto que veio para maiusculo.
			data[i] = toupper(data[i]);
			if(data[i] == ' '){
			}
		}
	}
	
	DEBUG_CLI(data);
	buff = strtok(data," ");

	//strcpy(tkn.tipo, buff);//type command (get/set)
	//tkn.tipo = (strcmp(buff, "GET")==0) ? GET_CMD : SET_CMD;
	if(strcmp(buff, "GET")==0) tkn.tipo = GET_CMD;
	else if(strcmp(buff, "SET")==0) tkn.tipo = SET_CMD;
	else if(strcmp(buff, "HELP")==0) tkn.tipo = HELP_CMD;
	else if(strcmp(buff, "CHAT")==0) tkn.tipo = CHAT_CMD;
	buff = strtok(NULL, " ");
	if (tkn.tipo == CHAT_CMD){
		strncpy(tkn.value, buff,j);//get porta.
		strncpy(tkn.cmd_name, "CHAT",j);//coloca o nome de CHAT.
		return 0;
	}
	strncpy(tkn.cmd_name, buff,j);//get name
	buff = strtok(NULL, " ");
	strcpy(tkn.value, buff);//get value
	//tkn.resp = "\0";

	//sprintf(buff, "Dados: Tipo %02d - Comando %s - Value - %s", tkn.tipo,tkn.cmd_name, tkn.value);
	//debug_cli(buff);

	return 0;
}

/*
 * Chama função para montar estrutura do comando
 * Busca função correspondete.
 *
 * Ao fim da execução dest_msg tera a resposta do sistema.
 *
 * Retorna:
 * 		 0 - caso a função não tenha retorno de dado.
 * 		-1 - caso de erro.
 * */
int CLI_Builder(char *data, char *dest){

	acpi = menu_cli;
	const cli_str* mCmd;
	char *buff;
	int ret=0,i=0;
	
	DEBUG_ENTER;

	strcpy(msg_dest, " ");

	if (strlen(data)<=2) return -1;
	mount_token(data);
	
	if(tkn.tipo == HELP_CMD){	//verifica se é um comando de help para todas as funções.
			help_func();
			strcpy(dest, msg_dest);
			return ret;
	}

	mCmd = acpi;
	for(i=0;;i++){
	//for(mCmd = acpi;;acpi++){//percorre toda a tabela de comandos a procura docomando.


		buff = mCmd->string;
		
		if(buff == NULL){
			DEBUG_ERROR(COMMAND_NOT_FOUND);
			unknown_cmd(tkn.cmd_name);
			strcpy(dest, msg_dest);
			return -1;
		}
		if(!strcmp(buff, tkn.cmd_name))	break; //achou a função correspondente.
		mCmd = acpi++;
	}

	DEBUG_CLI("Chamando função tratadora do comando.\n");
	ret = ExecCommand(mCmd);
	strcpy(dest, msg_dest);
	
	DEBUG_EXIT;
	//uart_puts(msg_dest);
	return ret;
}

void cmdExec(int (*ApiFunc) (str_t *tp)) {
	break_t error;
	DEBUG_ENTER;
	//executa função referente a chamada.
	
	error = (ApiFunc) (&tkn);	//executa função referente a chamada,passando como parametro a struct para retorno.
	DEBUG_CLI("OK.");
	if(error == RET_ERROR){
		DEBUG_ERROR(EXEC_COMMAND_ERROR);
		strcat(msg_dest,"COMMAND ERROR\n");
	}
	else {
		strcat(msg_dest, tkn.resp);
		strcat(msg_dest, "\n");
	}
	DEBUG_EXIT;
}


int ExecCommand(const cli_str* acp){

	strcpy(msg_dest, "\n");
	strcat(msg_dest, tkn.cmd_name);
	strcat(msg_dest, ": ");
	cmdExec(acp->pFunc);

	//debug_cli(msg_dest);
	
	return 0;
}


void UARTTakeString(char *str, char channel)
{
	int vd = 0xff;
	char tp[MAX_COMMAND_SIZE]="\0";
	char cond = '\n';
	do{
			vd = UARTReceiveByte(channel);
			uart_putc(vd);
		if (vd != cond) sprintf(tp, "%s%c", tp,vd);
	}while (vd != cond);
	strcpy(str, tp);
}

void set_IpDefault(void){
	vectorAddrIPv4[0] = 192;
	vectorAddrIPv4[1] = 168;
	vectorAddrIPv4[2] = 1;
	vectorAddrIPv4[3] = 13;
	set_IP();
}

void set_GatewayDefault(void){
	uip_GAT0 = 192;
	uip_GAT1 = 168;
	uip_GAT2 = 1;
	uip_GAT3 = 1;
	set_Gateway();
}

void set_MaskDefault(void){
	uip_Mask0 = 255;
	uip_Mask1 = 255;
	uip_Mask2 = 255;
	uip_Mask3 = 0;
	set_Mask();
}


/*
 * Apresenta todas as funcionalidades diponiveis com um help.
 * */
static void help_func(void){

	acpi = menu_cli;
	const cli_str* mCmd;
	char buff[200]="\0";
	int i;

	DEBUG_ENTER;

	mCmd = acpi++;
	strcpy(msg_dest,"\nFuncoes Basicas do Módulo Principal\n");
	for(i=0;;i++){
	//for(mCmd = acpi;mCmd->string != NULL;++acpi){//percorre toda a tabela de comandos.
		if(mCmd->string == NULL) break;
		sprintf(buff, "\n%20s\t - \t%s",mCmd->string,mCmd->help);
		strncat(msg_dest, buff, strlen(buff));

		mCmd = acpi++;
	}

	DEBUG_EXIT;
}


/*
 * Comando desconhecido de acordo com a tabela de comandos.
 * **/
static void unknown_cmd(char *str)
{
	char buff[100];
  if(strlen(str) > 0) {
    sprintf(buff, "Unknown command: %s\n", str);
    strcpy(msg_dest, buff);
  }
}


